/*
	r5code.h
	Author: Nathan Newman
	Header file for r5code.c

*/

#define RING_BUF_SIZE 15

/* Device Registers */
//PIC (Programmable interrupt controller)
#define PIC_MASK_REG 0x21
#define PIC_COMMAND_REG 0x20

//ACC (Asynchronous communications controller)
//ten 8-bit registers -- associated with seven I/O ports
//the seven addresses each consist of 
//the base address (COM1 or COM2) + an offset
//thus, the seven ports are base+0,...,base+6
#define COM1 0x3F8 //serial port 1 base address -- TODO: CHECK THIS ON OWN MACHINE!
#define COM2 0X2F8//serial port 2 base address -- TODO: CHECK THIS ON OWN MACHINE!

#define READWRITE_PORT_OFFSET 0
#define INTERRUPT_ENABLE_PORT_OFFSET 1
//these are in effect when bit 7 of the LINE_CONTROL register is set to 1 (otherwise, above two port values are in effect):
#define BRD_LSB_PORT_OFFSET 0
#define BRD_MSB_PORT_OFFSET 1

#define INTERRUPT_ID_PORT_OFFSET 2
#define LINE_CONTROL_PORT_OFFSET 3 
#define MODEM_CONTROL_PORT_OFFSET 4
#define LINE_STATUS_PORT_OFFSET 5
#define MODEM_STATUS_PORT_OFFSET 6

#define COM1_RDWR_PORT (COM1 + READWRITE_PORT_OFFSET)
#define COM1_INT_EN_PORT (COM1 + INTERRUPT_ENABLE_PORT_OFFSET)
#define COM1_BRD_LSB_PORT (COM1 + BRD_LSB_PORT_OFFSET)
#define COM1_BRD_MSB_PORT (COM1 + BRD_MSB_PORT_OFFSET)
#define COM1_INT_ID_PORT (COM1 + INTERRUPT_ID_PORT_OFFSET)
#define COM1_LN_CNTRL_PORT (COM1 + LINE_CONTROL_PORT_OFFSET)
#define COM1_MOD_CNTRL_PORT (COM1 + MODEM_CONTROL_PORT_OFFSET)
#define COM1_LN_STAT_PORT (COM1 + LINE_STATUS_PORT_OFFSET)
#define COM1_MOD_STAT_PORT (COM1 + MODEM_STATUS_PORT_OFFSET) 

//ACC interrupt details
#define COM1_INTERRUPT_ID 0x0C
#define COM2_INTERRUPT_ID 0x0B
//#define COM1_VECT_ADDR 0x0030
//#define COM2_VECT_ADDR 0x002C
#define COM1_PIC_LEVEL 4
#define COM2_PIC_LEVEL 3

//end of interrupt code
#define EOI 0x20

/* Error Codes */
//com_open error codes
#define INV_EVENTFLAG_PTR -101
#define INV_BAUD_RATE_DIV -102
#define PORT_ALREADY_OPEN -103
//com_close error codes
#define PORT_NOT_OPEN -201
//com_read error codes
#define PORT_NOT_OPEN_FOR_RD -301
#define INV_BUF_ADDR_FOR_RD -302
#define INV_COUNT_FOR_RD -303
#define DEV_BUSY_FOR_RD -304
//com_write error codes
#define PORT_NOT_OPEN_FOR_WR -401
#define INV_BUF_ADDR_FOR_WR -402
#define INV_COUNT_FOR_WR -403
#define DEV_BUSY_FOR_WR -404

/* Device Control Block */

//enumerated types



enum dcbStatus { READING, WRITING, IDLING }; 

//device control block struct definition
typedef struct dcb {
	int isOpen;
	int *event_flag_p;
	enum dcbStatus status;
	
	//addresses and counters associated with requester's input buffer
	char *in_buf; //ptr to requester's buff, where read data will be placed
	int *in_count_p; //ptr to counter of max num chars that CAN be placed in buff
	int in_done; //counter for how many chars HAVE been placed in buff
	
	//addresses and counters associated with requester's input buffer
	char *out_buf;
	int *out_count_p;
	int out_done;
	
	//ring buffer with indices and counter
	char ring_buf[RING_BUF_SIZE];
	int ring_buf_in; //index of next character insertion(write) location
	int ring_buf_out; //index of next character removal(read) location
	int ring_buf_count; //count of how many chars stored but not read from buff
	
} dcb; 


//prototypes (Note: "spih" stands for serial port interrupt handler)
int com_open(int*,int);
int com_close(void);
int com_read(char*,int*);
int com_write(char*,int*);
void interrupt level1_spih(void);
void level2in_spih(void);
void level2out_spih(void);
int printErr(int); 
void inspectDcb(void);
void testVect(void);